home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagd_f.zip / DOS.SWG / 0059_Enhanced DOS Interface.pas < prev    next >
Pascal/Delphi Source File  |  1994-08-24  |  54KB  |  2,236 lines

  1. {
  2. I'm very glad to be useful and to post the enhanced DOS unit for Turbo Pascal
  3. 7.0. It includes lots of nice routines written on inline asm, combined with
  4. short comments and explanations. All you have in standard DOS unit you may
  5. find in EnhDOS as well except of Exec and SwapVectors. Sure, the full source
  6. code!
  7.  
  8. What is good?
  9. -----------------
  10.  
  11. 1. Fast! (because of the asm)
  12. 2. Flexible! (less procedures, more functions, lots of parameters)
  13. 3. Good error-handling routines. (don't need to care to check errors at all)
  14. 4. _Strong_ file service. (lots of file functions)
  15. 5. Lots of additional DOS service functions that can't be found in any standard
  16.    or non-standard Pascal, C,... library.
  17. 6. Windows (tm) compatible (means you may use these routines when developing
  18.    Windows (tm) applications.
  19. 7. Own memory allocate/release routines. (used DOS memory allocation)
  20. 8. Free. Released to a Public Domain.
  21.  
  22. What is bad?
  23. -----------------
  24.  
  25. 1. Requires Borland Turbo Pascal version 7.0 or later (7.01)
  26. 2. Requires DOS 3.1 or later. Sorry guys, wanna cool service - need later DOS.
  27. 3. Won't run on XT personal computers. (uses 286 instructions)
  28. 4. No more strings. (all string-type names are of PChar type)
  29. 5. Exec and SwapVectors not implemented. If you'd like this code, I will
  30.    continue modifying this unit and will eventually add the above functions
  31.    too.
  32.  
  33. Well, routines were checked on IBM PS/2 386SX, seems like work fine!
  34.  
  35. Greetingz to
  36. -----------------
  37.  
  38.  Bas van Gaalen (cool asm programmer and my PASCAL area friend ;)
  39.  Dj Murdoch (best explainer ;)
  40.  Gayle Davis (SWAG live forever) Feel free to place it into a next SWAG bundle.
  41.  Ralph Brown (brilliant idea to make the interrupt list)
  42.  Alex Grischenko (whose asm help was very appreciated)
  43.  ...and all of you, guys!
  44.  
  45. Material used
  46. -----------------
  47.  
  48. Borland Pascal 7.0 Runtime Library source code
  49. Ralph Brown's Interrupt List
  50. Tech Help 4.0
  51.  
  52.  
  53. You may use this source-code-software in ANY purpose. Code may be changed.
  54. If some of the routines won't work, please send me a message.
  55. If you don't mind, please leave my copyright strings as they are.}
  56.  
  57. Unit EnhDOS;
  58. (*
  59.   Turbo Pascal 7.0 - ENHDOS.PAS
  60.  
  61.   Enhanced DOS interface unit for DOS 3.1+ ***  Version 1.1  April, 1994.
  62.   Copyright (c) 1994  by Andrew Eigus           Fidonet 2:5100/33
  63.  
  64.   Runtime Library Portions Copyright (c) 1991,92 Borland International }
  65.  
  66.   THIS UNIT SOURCE IS FREE
  67. *)
  68.  
  69. interface
  70.  
  71. {$X+} { Enable extended syntax }
  72. {$G+} { Enable 286+ instructions }
  73.  
  74. const
  75.  
  76.   { My copyright information }
  77.  
  78.   Copyright : PChar = 'Portions Copyright (c) 1994 by Andrew Eigus';
  79.  
  80.   { GetDriveType return values }
  81.  
  82.   dtError     = $00; { Bad drive }
  83.   dtFixed     = $01; { Fixed drive }
  84.   dtRemovable = $02; { Removable drive }
  85.   dtRemote    = $03; { Remote (network) drive }
  86.  
  87.   { Handle file open modes (om) constants }
  88.  
  89.   omRead           = $00; { Open file for input only }
  90.   omWrite          = $01; { Open file for output only }
  91.   omReadWrite      = $02; { Open file for input or/and output (both modes) }
  92.   omShareCompat    = $00; { Modes used when SHARE.EXE loaded }
  93.   omShareExclusive = $10;
  94.   omShareDenyWrite = $20;
  95.   omShareDenyRead  = $30;
  96.   omShareDenyNone  = $40;
  97.  
  98.   { Maximum file name component string lengths }
  99.  
  100.   fsPathName       = 79;
  101.   fsDirectory      = 67;
  102.   fsFileSpec       = 12;
  103.   fsFileName       = 8;
  104.   fsExtension      = 4;
  105.  
  106.   { FileSplit return flags }
  107.  
  108.   fcExtension      = $0001;
  109.   fcFileName       = $0002;
  110.   fcDirectory      = $0004;
  111.   fcWildcards      = $0008;
  112.  
  113.   { File attributes (fa) constants }
  114.  
  115.   faNormal         = $00;
  116.   faReadOnly       = $01;
  117.   faHidden         = $02;
  118.   faSysFile        = $04;
  119.   faVolumeID       = $08;
  120.   faDirectory      = $10;
  121.   faArchive        = $20;
  122.   faAnyFile        = $3F;
  123.  
  124.   { Seek start offset (sk) constants }
  125.  
  126.   skStart = 0; { Seek position relative to the beginning of a file }
  127.   skPos   = 1; { Seek position relative to a current file position }
  128.   skEnd   = 2; { Seek position relative to the end of a file }
  129.  
  130.   { Error handler function (fr) result codes }
  131.  
  132.   frOk    = 0; { Continue program }
  133.   frRetry = 1; { Retry function once again }
  134.  
  135.   { Function codes (only passed to error handler routine) (fn) constants }
  136.  
  137.   fnGetDPB         = $3200;
  138.   fnGetDiskSize    = $3600;
  139.   fnGetDiskFree    = $3601;
  140.   fnGetCountryInfo = $3800;
  141.   fnSetDate        = $2B00;
  142.   fnSetTime        = $2D00;
  143.   fnIsFixedDisk    = $4408;
  144.   fnIsNetworkDrive = $4409;
  145.   fnCreateDir      = $3900;
  146.   fnRemoveDir      = $3A00;
  147.   fnGetCurDir      = $4700;
  148.   fnSetCurDir      = $3B00;
  149.   fnDeleteFile     = $4100;
  150.   fnRenameFile     = $5600;
  151.   fnGetFileAttr    = $4300;
  152.   fnSetFileAttr    = $4301;
  153.   fnFindFirst      = $4E00;
  154.   fnFindNext       = $4F00;
  155.   fnCreateFile     = $5B00;
  156.   fnCreateTempFile = $5A00;
  157.   fnOpenFile       = $3D00;
  158.   fnRead           = $3F00;
  159.   fnWrite          = $4000;
  160.   fnSeek           = $4200;
  161.   fnGetFDateTime   = $5700;
  162.   fnSetFDateTime   = $5701;
  163.   fnCloseFile      = $3E00;
  164.   fnMemAlloc       = $4800;
  165.   fnMemFree        = $4900;
  166.  
  167.   { DOS 3.x+ errors/return codes }
  168.  
  169.   dosrOk                = 0;   { Success }
  170.   dosrInvalidFuncNumber = 1;   { Invalid DOS function number }
  171.   dosrFileNotFound      = 2;   { File not found }
  172.   dosrPathNotFound      = 3;   { Path not found }
  173.   dosrTooManyOpenFiles  = 4;   { Too many open files }
  174.   dosrFileAccessDenied  = 5;   { File access denied }
  175.   dosrInvalidFileHandle = 6;   { Invalid file handle }
  176.   dosrNotEnoughMemory   = 8;   { Not enough memory }
  177.   dosrInvalidEnvment    = 10;  { Invalid environment }
  178.   dosrInvalidFormat     = 11;  { Invalid format }
  179.   dosrInvalidAccessCode = 12;  { Invalid file access code }
  180.   dosrInvalidDrive      = 15;  { Invalid drive number }
  181.   dosrCantRemoveDir     = 16;  { Cannot remove current directory }
  182.   dosrCantRenameDrives  = 17;  { Cannot rename across drives }
  183.   dosrNoMoreFiles       = 18;  { No more files }
  184.  
  185. type
  186.  
  187.   TPathStr = array[0..fsPathName] of Char;
  188.   TDirStr  = array[0..fsDirectory] of Char;
  189.   TNameStr = array[0..fsFileName] of Char;
  190.   TExtStr  = array[0..fsExtension] of Char;
  191.   TFileStr = array[0..fsFileSpec] of Char;
  192.  
  193.   { Disk information block structure }
  194.  
  195.   PDiskParamBlock = ^TDiskParamBlock;
  196.   TDiskParamBlock = record
  197.     Drive : byte;             { Disk drive number (0=A, 1=B, 2=C...) }
  198.     SubunitNum : byte;        { Sub-unit number from driver device header }
  199.     SectSize : word;          { Number of bytes per sector }
  200.     SectPerClust : byte;      { Number of sectors per cluster -1
  201.                                 (max sector in cluster) }
  202.     ClustToSectShft : byte;   { Cluster-to-sector shift }
  203.     BootSize : word;          { Reserved sectors (boot secs; start of root dir}
  204.     FATCount : byte;          { Number of FATs }
  205.     MaxDir : word;            { Number of directory entries allowed in root }
  206.     DataSect : word;          { Sector number of first data cluster }
  207.     Clusters : word;          { Total number of allocation units (clusters)
  208.                                 +2 (number of highest cluster) }
  209.     FATSectors : byte;        { Sectors needed by first FAT }
  210.     RootSect : word;          { Sector number of start of root directory }
  211.     DeviceHeader : pointer;   { Address of device header }
  212.     Media : byte;             { Media descriptor byte }
  213.     AccessFlag : byte;        { 0 if drive has been accessed }
  214.     NextPDB : pointer         { Address of next DPB (0FFFFh if last) }
  215.   end;
  216.  
  217.   { Disk allocation data structure }
  218.  
  219.   PDiskAllocInfo = ^TDiskAllocInfo;
  220.   TDiskAllocInfo = record
  221.     FATId : byte;             { FAT Id }
  222.     Clusters : word;          { Number of allocation units (clusters) }
  223.     SectPerClust : byte;      { Number of sectors per cluster }
  224.     SectSize : word           { Number of bytes per sector }
  225.   end;
  226.  
  227.   { Country information structure }
  228.  
  229.   PCountryInfo = ^TCountryInfo;
  230.   TCountryInfo = record
  231.     DateFormat : word; { Date format value may be one of the following:
  232.                          0 - Month, Day, Year     (USA)
  233.                          1 - Day, Month, Year     (Europe)
  234.                          2 - Year, Month, Day     (Japan) }
  235.  
  236.     CurrencySymbol : array[0..4] of Char; { Currency symbol string }
  237.     ThousandsChar : byte; { Thousands separator character }
  238.     reserved1 : byte;
  239.     DecimalChar : byte;   { Decimal separator character }
  240.     reserved2 : byte;
  241.     DateChar : byte;      { Date separator character }
  242.     reserved3 : byte;
  243.     TimeChar : byte;      { Time separator character }
  244.     reserved4 : byte;
  245.     CurrencyFormat : byte; { Currency format:
  246.                              $XXX.XX
  247.                              XXX.XX$
  248.                              $ XXX.XX
  249.                              XXX.XX $
  250.                              XXX$XX }
  251.  
  252.     Digits : byte;          { Number of digits after decimal in currency }
  253.     TimeFormat : byte;      { Time format may be one of the following:
  254.                               bit 0 = 0 if 12 hour clock
  255.                                   1 if 24 hour clock }
  256.  
  257.     MapRoutine : pointer;   { Address of case map routine FAR CALL,
  258.                               AL - character to map to upper case [>=80h] }
  259.  
  260.     DataListChar : byte;    { Data-list separator character }
  261.     reserved5 : byte;
  262.     reserved6 : array[1..10] of Char
  263.   end;
  264.  
  265.   THandle = Word; { Handle type (file handle and memory handle functions) }
  266.  
  267.   { Error handler function }
  268.  
  269.   TErrorFunc = function(ErrCode : integer; FuncCode : word) : byte;
  270.  
  271.   { Search record used by FindFirst and FindNext }
  272.  
  273.   TSearchRec = record
  274.     Fill : array[1..21] of Byte;
  275.     Attr : byte;
  276.     Time : longint;
  277.     Size : longint;
  278.     Name : TFileStr
  279.   end;
  280.  
  281.   { Date and time record used by PackTime and UnpackTime }
  282.  
  283.   TDateTime = record
  284.     Year,
  285.     Month,
  286.     Day,
  287.     Hour,
  288.     Min,
  289.     Sec : word
  290.   end;
  291.  
  292.  
  293. var
  294.   DOSResult : integer; { Error status variable }
  295.   TempStr : array[0..High(String)] of Char;
  296.  
  297. function SetErrorHandler(Handler : TErrorFunc) : pointer;
  298. function Pas2PChar(S : string) : PChar;
  299.  
  300. function GetInDOSFlag : boolean;
  301. function GetDOSVersion : word;
  302. function GetSwitchChar : char;
  303. function SetSwitchChar(Switch : char) : byte;
  304. function GetCountryInfo(var Info : TCountryInfo) : integer;
  305. procedure GetDate(var Year : word; var Month, Day, DayOfWeek : byte);
  306. function SetDate(Year : word; Month, Day : byte) : boolean;
  307. procedure GetTime(var Hour, Minute, Second, Sec100 : byte);
  308. function SetTime(Hour, Minute, Second, Sec100 : byte) : boolean;
  309. function GetCBreak : boolean;
  310. function SetCBreak(Break : boolean) : boolean;
  311. function GetVerify : boolean;
  312. function SetVerify(Verify : boolean) : boolean;
  313. function GetArgCount : integer;
  314. function GetArgStr(Dest : PChar; Index : integer; MaxLen : word) : PChar;
  315. function GetEnvVar(VarName : PChar) : PChar;
  316. function GetIntVec(IntNo : byte; var Vector : pointer) : pointer;
  317. function SetIntVec(IntNo : byte; Vector : pointer) : pointer;
  318.  
  319. function GetDTA : pointer;
  320. function GetCurDisk : byte;
  321. function SetCurDisk(Drive : byte) : byte;
  322. procedure GetDriveAllocInfo(Drive : byte; var Info : TDiskAllocInfo);
  323. function GetDPB(Drive : byte; var DPB : TDiskParamBlock) : integer;
  324. function DiskSize(Drive : byte) : longint;
  325. function DiskFree(Drive : byte) : longint;
  326. function IsFixedDisk(Drive : byte) : boolean;
  327. function IsNetworkDrive(Drive : byte) : boolean;
  328. function GetDriveType(Drive : byte) : byte;
  329.  
  330. function CreateDir(Dir : PChar) : integer;
  331. function RemoveDir(Dir : PChar) : integer;
  332. function GetCurDir(Drive : byte; Dir : PChar) : integer;
  333. function SetCurDir(Dir : PChar) : integer;
  334.  
  335. function DeleteFile(Path : PChar) : integer;
  336. function RenameFile(OldPath, NewPath : PChar) : integer;
  337. function ExistsFile(Path : PChar) : boolean;
  338. function GetFileAttr(Path : PChar) : integer;
  339. function SetFileAttr(Path : PChar; Attr : word) : integer;
  340. function FindFirst(Path : PChar; Attr: word; var F : TSearchRec) : integer;
  341. function FindNext(var F : TSearchRec) : integer;
  342. procedure UnpackTime(P : longint; var T : TDateTime);
  343. function PackTime(var T : TDateTime) : longint;
  344.  
  345. function h_CreateFile(Path : PChar) : THandle;
  346. function h_CreateTempFile(Path : PChar) : THandle;
  347. function h_OpenFile(Path : PChar; Mode : byte) : THandle;
  348. function h_Read(Handle : THandle; var Buffer; Count : word) : word;
  349. function h_Write(Handle : THandle; var Buffer; Count : word) : word;
  350. function h_Seek(Handle : THandle; SeekPos : longint; Start : byte) : longint;
  351. function h_FilePos(Handle : THandle) : longint;
  352. function h_FileSize(Handle : THandle) : longint;
  353. function h_Eof(Handle : THandle) : boolean;
  354. function h_GetFTime(Handle : THandle) : longint;
  355. function h_SetFTime(Handle : THandle; DateTime : longint) : longint;
  356. function h_CloseFile(Handle : THandle) : integer;
  357.  
  358. function MemAlloc(Size : longint) : pointer;
  359. function MemFree(P : pointer) : integer;
  360.  
  361. function FileSearch(Dest, Name, List : PChar) : PChar;
  362. function FileExpand(Dest, Name : PChar) : PChar;
  363. function FileSplit(Path, Dir, Name, Ext : PChar) : word;
  364.  
  365. implementation
  366.  
  367. {$IFDEF Windows}
  368. {$DEFINE ProtectedMode}
  369. {$ENDIF}
  370.  
  371. {$IFDEF DPMI}
  372. {$DEFINE ProtectedMode}
  373. {$ENDIF}
  374.  
  375. {$IFDEF Windows}
  376.  
  377. uses WinTypes, WinProcs, Strings;
  378.  
  379. {$ELSE}
  380.  
  381. uses Strings;
  382.  
  383. {$ENDIF}
  384.  
  385. const DOS = $21; { DOS interrupt number }
  386.  
  387. var
  388.   ErrorHandler : TErrorFunc;
  389.  
  390. Function SetErrorHandler;
  391. { Sets the new error handler to hook all errors returned by EnhDOS functions,
  392.   and returns the pointer to an old interrupt handler routine }
  393. Begin
  394.   SetErrorHandler := @ErrorHandler;
  395.   ErrorHandler := Handler
  396. End; { SetErrorHandler }
  397.  
  398. Function Pas2PChar(S : string) : PChar;
  399. { Returns PChar type equivalent of the S variable. Use this function
  400.   to convert strings to PChars }
  401. Begin
  402.   Pas2PChar := StrPCopy(TempStr, S)
  403. End; { Pas2PChar }
  404.  
  405. {$IFDEF Windows}
  406.  
  407. procedure AnsiDosFunc; assembler;
  408. asm
  409.   PUSH DS
  410.   PUSH CX
  411.   PUSH AX
  412.   MOV SI,DI
  413.   PUSH ES
  414.   POP DS
  415.   LEA DI,TempStr
  416.   PUSH SS
  417.   POP ES
  418.   MOV CX,fsPathName
  419.   CLD
  420. @@1:
  421.   LODSB
  422.   OR  AL,AL
  423.   JE  @@2
  424.   STOSB
  425.   LOOP @@1
  426. @@2:
  427.   XOR AL,AL
  428.   STOSB
  429.   LEA DI,TempStr
  430.   PUSH SS
  431.   PUSH DI
  432.   PUSH SS
  433.   PUSH DI
  434.   CALL AnsiToOem
  435.   POP AX
  436.   POP CX
  437.   LEA DX,TempStr
  438.   PUSH SS
  439.   POP DS
  440.   INT DOS
  441.   POP DS
  442. end; { AnsiDosFunc /Windows }
  443.  
  444. {$ELSE}
  445.  
  446. procedure AnsiDosFunc; assembler;
  447. asm
  448.   PUSH DS
  449.   MOV DX,DI
  450.   PUSH ES
  451.   POP DS
  452.   INT DOS
  453.   POP DS
  454. end; { AnsiDosFunc }
  455.  
  456. {$ENDIF}
  457.  
  458. Function GetInDOSFlag; assembler;
  459. { GETINDOSFLAG - DOS service function
  460.   Description: Returns the current state of InDOS flag; fn=34h
  461.   Returns: True if a DOS operation is being performed, False if there is
  462.            no DOS command that currently is running }
  463. Asm
  464.   MOV AH,34h
  465.   INT DOS
  466.   MOV AL,BYTE PTR [ES:BX]
  467. End; { GetInDOSFlag }
  468.  
  469. Function GetDOSVersion; assembler;
  470. { GETDOSVERSION - DOS service function
  471.   Description: Retrieves DOS version number; fn=30h
  472.   Returns: Major DOS version number in low-order byte,
  473.            minor version number in high-order byte of word }
  474. Asm
  475.   MOV AH,30h
  476.   INT DOS
  477. End; { GetDOSVersion }
  478.  
  479. Function GetSwitchChar; assembler;
  480. { GETSWITCHCHAR - DOS service function
  481.   Description: Retrieves DOS command line default switch character; fn=37h
  482.   Returns: Switch character ('/', '-', ...) or FFh if unsupported subfunction }
  483. Asm
  484.   MOV AH,37h
  485.   XOR AL,AL
  486.   INT DOS
  487.   CMP AL,0FFh
  488.   JE  @@1
  489.   MOV AL,DL
  490. @@1:
  491. End; { GetSwitchChar }
  492.  
  493. Function SetSwitchChar; assembler;
  494. { SETSWITCHCHAR - DOS service function
  495.   Description: Sets new DOS command line switch character; fn=37h
  496.   Returns: FFh if unsupported subfunction, any other value success }
  497. Asm
  498.   MOV AX,3701h
  499.   MOV DL,Switch
  500.   INT DOS
  501. End; { SetSwitchChar }
  502.  
  503. Function GetCountryInfo; assembler;
  504. { GETCOUNTRYINFO - DOS service function
  505.   Description: Retrieves country information; fn=38h
  506.   Returns: Country code if successful, negative DOS error code otherwise }
  507. Asm
  508. @@1:
  509.   PUSH DS
  510.   MOV AH,38h
  511.   XOR AL,AL
  512.   LDS DX,Info
  513.   INT DOS
  514.   POP DS
  515.   JC  @@2
  516.   MOV AX,BX
  517.   MOV DOSResult,dosrOk
  518.   JMP @@3
  519. @@2:
  520.   MOV DOSResult,AX { save error code in global variable }
  521.   PUSH AX     { store error code }
  522.   PUSH fnGetCountryInfo { store function code }
  523.   CALL ErrorHandler
  524.   CMP AL,frRetry
  525.   JE  @@1
  526.   POP AX
  527.   NEG AX
  528. @@3:
  529. End; { GetCountryInfo }
  530.  
  531. Procedure GetDate; assembler;
  532. { GETDATE - DOS service function
  533.   Description: Retrieves the current date set in the operating system.
  534.                Ranges of the values returned are: Year 1980-2099,
  535.                Month 1-12, Day 1-31 and DayOfWeek 0-6 (0 corresponds to
  536.                Sunday) }
  537. Asm
  538.   MOV AH,2AH
  539.   INT DOS
  540.   XOR AH,AH
  541.   LES DI,DayOfWeek
  542.   STOSB
  543.   MOV AL,DL
  544.   LES DI,Day
  545.   STOSB
  546.   MOV AL,DH
  547.   LES DI,Month
  548.   STOSB
  549.   XCHG AX,CX
  550.   LES DI,Year
  551.   STOSW
  552. End; { GetDate }
  553.  
  554. Function SetDate; assembler;
  555. { SETDATE - DOS service function
  556.   Description: Sets the current date in the operating system. Valid
  557.                parameter ranges are: Year 1980-2099, Month 1-12 and
  558.                Day 1-31
  559.   Returns: True if the date was set, False if the date is not valid }
  560. Asm
  561.   MOV CX,Year
  562.   MOV DH,Month
  563.   MOV DL,Day
  564.   MOV AH,2BH
  565.   INT DOS
  566.   CMP AL,0
  567.   JE  @@1
  568.   MOV DOSResult,AX
  569.   PUSH AX
  570.   PUSH fnSetDate
  571.   CALL ErrorHandler
  572.   MOV AL,True
  573. @@1:
  574.   NOT AL
  575. End; { SetDate }
  576.  
  577. Procedure GetTime; assembler;
  578. { GETTIME - DOS service function
  579.   Description: Returns the current time set in the operating system.
  580.                Ranges of the values returned are: Hour 0-23, Minute 0-59,
  581.                Second 0-59 and Sec100 (hundredths of seconds) 0-99 }
  582. Asm
  583.   MOV AH,2CH
  584.   INT DOS
  585.   XOR AH,AH
  586.   MOV AL,DL
  587.   LES DI,Sec100
  588.   STOSB
  589.   MOV AL,DH
  590.   LES DI,Second
  591.   STOSB
  592.   MOV AL,CL
  593.   LES DI,Minute
  594.   STOSB
  595.   MOV AL,CH
  596.   LES DI,Hour
  597.   STOSB
  598. End; { GetTime }
  599.  
  600. Function SetTime; assembler;
  601. { SETTIME - DOS service function
  602.   Description: Sets the time in the operating system. Valid
  603.                parameter ranges are: Hour 0-23, Minute 0-59, Second 0-59 and
  604.                Sec100 (hundredths of seconds) 0-99
  605.   Returns: True if the time was set, False if the time is not valid }
  606. Asm
  607.   MOV CH,Hour
  608.   MOV CL,Minute
  609.   MOV DH,Second
  610.   MOV DL,Sec100
  611.   MOV AH,2DH
  612.   INT DOS
  613.   CMP AL,0
  614.   JE  @@1
  615.   MOV DOSResult,AX
  616.   PUSH AX
  617.   PUSH fnSetTime
  618.   CALL ErrorHandler
  619.   MOV AL,True
  620. @@1:
  621.   NOT AL
  622. End; { SetTime }
  623.  
  624. Function GetCBreak; assembler;
  625. { GETCBREAK - DOS service function
  626.   Description: Retrieves Control-Break state; fn=3300h
  627.   Returns: Current Ctrl-Break state }
  628. Asm
  629.   MOV AX,3300h
  630.   INT DOS
  631.   MOV AL,DL
  632. End; { GetCBreak }
  633.  
  634. Function SetCBreak; assembler;
  635. { SETCBREAK - DOS service function
  636.   Description: Sets new Control-Break state; fn=3300h
  637.   Returns: Old Ctrl-Break state }
  638. Asm
  639.   CALL GetCBreak
  640.   PUSH AX
  641.   MOV AX,3301h
  642.   MOV DL,Break
  643.   INT DOS
  644.   POP AX
  645. End; { SetCBreak }
  646.  
  647. Function GetVerify; assembler;
  648. { GETVERIFY - DOS service function
  649.   Description: Returns the state of the verify flag in DOS.
  650.                When off (False), disk writes are not verified.
  651.                When on (True), all disk writes are verified to insure proper
  652.                writing; fn=54h
  653.   Returns: State of the verify flag }
  654. Asm
  655.   MOV AH,54H
  656.   INT DOS
  657. End; { GetVerify }
  658.  
  659. Function SetVerify; assembler;
  660. { SETVERIFY - DOS service function
  661.   Description: Sets the state of the verify flag in DOS; fn=2Eh
  662.   Returns: Previous state of the verify flag }
  663. Asm
  664.   CALL GetVerify
  665.   PUSH AX
  666.   MOV AL,Verify
  667.   MOV AH,2EH
  668.   INT DOS
  669.   POP AX
  670. End; { SetVerify }
  671.  
  672. {$IFDEF Windows}
  673.  
  674. Procedure ArgStrCount; assembler;
  675. Asm
  676.   LDS SI,CmdLine
  677.   CLD
  678. @@1:
  679.   LODSB
  680.   OR  AL,AL
  681.   JE  @@2
  682.   CMP AL,' '
  683.   JBE @@1
  684. @@2:
  685.   DEC SI
  686.   MOV BX,SI
  687. @@3:
  688.   LODSB
  689.   CMP AL,' '
  690.   JA  @@3
  691.   DEC SI
  692.   MOV AX,SI
  693.   SUB AX,BX
  694.   JE  @@4
  695.   LOOP @@1
  696. @@4:
  697. End; { ArgStrCount /Windows }
  698.  
  699. Function GetArgCount; assembler;
  700. { GETARGCOUNT - DOS service function
  701.   Description: Returns the number of parameters passed to the
  702.                program on the command line
  703.   Returns: Actual number of command line parameters }
  704.  
  705. Asm
  706.   PUSH DS
  707.   XOR  CX,CX
  708.   CALL ArgStrCount
  709.   XCHG AX,CX
  710.   NEG AX
  711.   POP DS
  712. End; { GetArgCount /Windows }
  713.  
  714. Function GetArgStr; assembler;
  715. { GETARGSTR - DOS service function
  716.   Description: Returns the specified parameter from the command line
  717.   Returns: ASCIIZ parameter, or an empty string if Index is less than zero
  718.            or greater than GetArgCount. If Index is zero, GetArgStr returns
  719.            the filename of the current module. The maximum length of the
  720.            string returned in Dest is given by the MaxLen parameter. The
  721.            returned value is Dest }
  722.  
  723. Asm
  724.   MOV CX,Index
  725.   JCXZ @@2
  726.   PUSH DS
  727.   CALL ArgStrCount
  728.   MOV SI,BX
  729.   LES DI,Dest
  730.   MOV CX,MaxLen
  731.   CMP CX,AX
  732.   JB  @@1
  733.   XCHG AX,CX
  734. @@1:
  735.   REP MOVSB
  736.   XCHG AX,CX
  737.   STOSB
  738.   POP DS
  739.   JMP @@3
  740. @@2:
  741.   PUSH HInstance
  742.   PUSH WORD PTR [Dest+2]
  743.   PUSH WORD PTR [Dest]
  744.   MOV AX,MaxLen
  745.   INC AX
  746.   PUSH AX
  747.   CALL GetModuleFileName
  748. @@3:
  749.   MOV AX,WORD PTR [Dest]
  750.   MOV DX,WORD PTR [Dest+2]
  751. End; { GetArgStr /Windows }
  752.  
  753. {$ELSE}
  754.  
  755. Procedure ArgStrCount; assembler;
  756. Asm
  757.   MOV DS,PrefixSeg
  758.   MOV SI,80H
  759.   CLD
  760.   LODSB
  761.   MOV DL,AL
  762.   XOR DH,DH
  763.   ADD DX,SI
  764. @@1:
  765.   CMP SI,DX
  766.   JE  @@2
  767.   LODSB
  768.   CMP AL,' '
  769.   JBE @@1
  770.   DEC SI
  771. @@2:
  772.   MOV BX,SI
  773. @@3:
  774.   CMP SI,DX
  775.   JE  @@4
  776.   LODSB
  777.   CMP AL,' '
  778.   JA  @@3
  779.   DEC SI
  780. @@4:
  781.   MOV AX,SI
  782.   SUB AX,BX
  783.   JE  @@5
  784.   LOOP @@1
  785. @@5:
  786. End; { ArgStrCount }
  787.  
  788. Function GetArgCount; assembler;
  789. { GETARGCOUNT - DOS service function
  790.   Description: Returns the number of parameters passed to the
  791.                program on the command line
  792.   Returns: Actual number of command line parameters }
  793. Asm
  794.   PUSH DS
  795.   XOR CX,CX
  796.   CALL ArgStrCount
  797.   XCHG AX,CX
  798.   NEG AX
  799.   POP DS
  800. End; { GetArgCount }
  801.  
  802. Function GetArgStr; assembler;
  803. { GETARGSTR - DOS service function
  804.   Description: Returns the specified parameter from the command line
  805.   Returns: ASCIIZ parameter, or an empty string if Index is less than zero
  806.            or greater than GetArgCount. If Index is zero, GetArgStr returns
  807.            the filename of the current module. The maximum length of the
  808.            string returned in Dest is given by the MaxLen parameter. The
  809.            returned value is Dest }
  810. Asm
  811.   PUSH DS
  812.   MOV CX,Index
  813.   JCXZ @@1
  814.   CALL ArgStrCount
  815.   MOV SI,BX
  816.   JMP @@4
  817. @@1:
  818.   MOV AH,30H
  819.   INT DOS
  820.   CMP AL,3
  821.   MOV AX,0
  822.   JB  @@4
  823.   MOV DS,PrefixSeg
  824.   MOV ES,DS:WORD PTR 2CH
  825.   XOR DI,DI
  826.   CLD
  827. @@2:
  828.   CMP AL,ES:[DI]
  829.   JE  @@3
  830.   MOV CX,-1
  831.   REPNE SCASB
  832.   JMP @@2
  833. @@3:
  834.   ADD DI,3
  835.   MOV SI,DI
  836.   PUSH ES
  837.   POP DS
  838.   MOV CX,256
  839.   REPNE SCASB
  840.   XCHG AX,CX
  841.   NOT AL
  842. @@4:
  843.   LES DI,Dest
  844.   MOV CX,MaxLen
  845.   CMP CX,AX
  846.   JB  @@5
  847.   XCHG AX,CX
  848. @@5:
  849.   REP MOVSB
  850.   XCHG AX,CX
  851.   STOSB
  852.   MOV AX,WORD PTR [Dest]
  853.   MOV DX,WORD PTR [Dest+2]
  854.   POP DS
  855. End; { GetArgStr }
  856.  
  857. {$ENDIF}
  858.  
  859. Function GetEnvVar;
  860. { GETENVVAR - DOS service function
  861.   Description: Retrieves a specified DOS environment variable
  862.   Returns: A pointer to the value of a specified variable,
  863.            i.e. a pointer to the first character after the equals
  864.            sign (=) in the environment entry given by VarName.
  865.            VarName is case insensitive. GetEnvVar returns NIL if
  866.            the specified environment variable does not exist }
  867. var
  868.   L : word;
  869.   P : PChar;
  870. Begin
  871.   L := StrLen(VarName);
  872. {$IFDEF Windows}
  873.   P := GetDosEnvironment;
  874. {$ELSE}
  875.   P := Ptr(Word(Ptr(PrefixSeg, $2C)^), 0);
  876. {$ENDIF}
  877.   while P^ <> #0 do
  878.   begin
  879.     if (StrLIComp(P, VarName, L) = 0) and (P[L] = '=') then
  880.     begin
  881.       GetEnvVar := P + L + 1;
  882.       Exit;
  883.     end;
  884.     Inc(P, StrLen(P) + 1)
  885.   end;
  886.   GetEnvVar := nil
  887. End; { GetEnvVar }
  888.  
  889. Function GetIntVec; assembler;
  890. { GETINTVEC - DOS service function
  891.   Description: Retrieves the address stored in the specified interrupt vector
  892.   Returns: A pointer to this address }
  893. Asm
  894.   MOV AL,IntNo
  895.   MOV AH,35H
  896.   INT DOS
  897.   MOV AX,ES
  898.   LES DI,Vector
  899.   CLD
  900.   MOV DX,BX
  901.   XCHG AX,BX
  902.   STOSW
  903.   XCHG AX,BX
  904.   STOSW
  905.   XCHG AX,DX
  906. End; { GetIntVec }
  907.  
  908. Function SetIntVec; assembler;
  909. { SETINTVEC - DOS Service function
  910.   Description: Sets the address in the interrupt vector table for the
  911.                specified interrupt
  912.   Returns: The old address of the specified interrupt vector }
  913. Asm
  914.   LES DI,Vector
  915.   PUSH WORD PTR IntNo
  916.   PUSH ES
  917.   PUSH DI
  918.   PUSH CS
  919.   CALL GetIntVec
  920.   PUSH DX
  921.   PUSH AX
  922.   PUSH DS
  923.   LDS DX,Vector
  924.   MOV AL,IntNo
  925.   MOV AH,25H
  926.   INT DOS
  927.   POP DS
  928.   POP AX
  929.   POP DX
  930. End; { SetIntVec }
  931.  
  932. Function GetDTA; assembler;
  933. { GETDTA - DOS service function
  934.   Description: Retrieves a pointer address to a DOS data exchange buffer (DTA).
  935.                By default, DTA address has the offset PSP+80h and the size of
  936.                128 bytes. DTA is used to access files with the FCB method;
  937.                fn=2Fh
  938.   Returns: A pointer address to DTA }
  939. Asm
  940.   MOV AH,2Fh
  941.   INT DOS
  942.   MOV DX,BX { store offset }
  943.   MOV AX,ES { store segment }
  944. End; { GetDTA }
  945.  
  946. Function GetCurDisk; assembler;
  947. { GETCURDISK - DOS disk service function
  948.   Description: Retrieves number of disk currently being active; fn=19h
  949.   Returns: Default (current, active) disk number }
  950. Asm
  951.   MOV AH,19h
  952.   INT DOS
  953. End; { GetCurDisk }
  954.  
  955. Function SetCurDisk; assembler;
  956. { SETCURDISK - DOS disk service function
  957.   Description: Sets current (default/active) drive; fn=0Eh
  958.   Returns: Number of disks in the system }
  959. Asm
  960.   MOV AH,0Eh
  961.   MOV DL,Drive
  962.   INT DOS
  963. End; { SetCurDisk }
  964.  
  965. Procedure GetDriveAllocInfo; assembler;
  966. { GETDRIVEALLOCINFO - DOS disk service function
  967.   Description: Retrieves disk allocation information; fn=1Ch
  968.   Retrieves Info structure }
  969. Asm
  970.   PUSH DS
  971.   MOV AH,1Ch
  972.   MOV DL,Drive
  973.   INT DOS
  974.   MOV AH,BYTE PTR [DS:BX]
  975.   LES DI,Info
  976.   MOV BYTE PTR ES:[DI],AH      { Info.FATId }
  977.   MOV WORD PTR ES:[DI+1],DX    { Info.Clusters }
  978.   MOV BYTE PTR ES:[DI+3],AL    { Info.SectorsPerCluster }
  979.   MOV WORD PTR ES:[DI+4],CX    { Info.BytesPerSector }
  980.   POP DS
  981. End; { GetDriveAllocInfo }
  982.  
  983. Function GetDPB; assembler;
  984. { GETDPB - DOS disk service function (undocumented)
  985.   Description: Returns a block of information that is useful for applications
  986.                which perform sector-level access of disk drives supported by
  987.                device drivers; fn=32h
  988.   Returns: 0 if successful, negative dosrInvalidDrive error code otherwise
  989.   Remarks: Use 0 for default drive }
  990. Asm
  991.   MOV DOSResult,dosrOk
  992.   PUSH DS
  993.   MOV AH,32h
  994.   MOV DL,Drive
  995.   INT DOS
  996.   MOV WORD PTR [DPB],DS
  997.   MOV WORD PTR [DPB+2],BX
  998.   POP DS
  999.   XOR AH,AH
  1000.   CMP AL,0FFh
  1001.   JNE @@1
  1002.   MOV DOSResult,dosrInvalidDrive
  1003.   PUSH DOSResult
  1004.   PUSH fnGetDPB
  1005.   CALL ErrorHandler
  1006.   MOV AX,DOSResult
  1007.   NEG AX
  1008. @@1:
  1009. End; { GetDPB }
  1010.  
  1011. Function DiskSize; assembler;
  1012. { DISKSIZE - DOS disk service function
  1013.   Description: Retrieves total disk size; fn=36h
  1014.   Returns: Total disk size in bytes if successful, negative dosrInvalidDrive
  1015.            error code otherwise
  1016.   Remarks: Use 0 for default drive }
  1017. Asm
  1018. @@1:
  1019.   MOV AH,36h
  1020.   MOV DL,Drive
  1021.   INT DOS
  1022.   CMP AX,0FFFFh
  1023.   JE  @@2
  1024.   MOV BX,DX
  1025.   IMUL CX
  1026.   IMUL BX
  1027.   JMP @@3
  1028. @@2:
  1029.   MOV DOSResult,dosrInvalidDrive
  1030.   PUSH DOSResult
  1031.   PUSH fnGetDiskSize
  1032.   CALL ErrorHandler
  1033.   CMP AL,frRetry
  1034.   JE  @@1
  1035.   MOV AX,DOSResult
  1036.   NEG AX
  1037.   XOR DX,DX
  1038. @@3:
  1039. End; { DiskSize }
  1040.  
  1041. Function DiskFree; assembler;
  1042. { DISKFREE - DOS disk service function
  1043.   Description: Retrieves amount of free disk space; fn=36h
  1044.   Returns: Amount of free disk space in bytes if successful,
  1045.            negative dosrInvalidDrive error code otherwise
  1046.   Remarks: Use 0 for default drive }
  1047. Asm
  1048. @@1:
  1049.   MOV AH,36h
  1050.   MOV DL,Drive
  1051.   INT DOS
  1052.   CMP AX,0FFFFh
  1053.   JE  @@2
  1054.   IMUL CX
  1055.   IMUL BX
  1056.   JMP @@3
  1057. @@2:
  1058.   MOV DOSResult,dosrInvalidDrive
  1059.   PUSH DOSResult
  1060.   PUSH fnGetDiskFree
  1061.   CALL ErrorHandler
  1062.   CMP AL,frRetry
  1063.   JE  @@1
  1064.   MOV AX,DOSResult
  1065.   NEG AX
  1066.   XOR DX,DX
  1067. @@3:
  1068. End; { DiskFree }
  1069.  
  1070. Function IsFixedDisk; assembler;
  1071. { ISFIXEDDISK - DOS disk service function
  1072.   Description: Ensures whether the specified disk is fixed or removable;
  1073.                fn=4408h
  1074.   Returns: True, if the disk is fixed, False - otherwise
  1075.   Remarks: Use 0 for default (current) drive }
  1076. Asm
  1077.   MOV AX,4408h
  1078.   MOV BL,Drive
  1079.   INT DOS
  1080.   JNC @@1
  1081.   MOV DOSResult,AX { save error code in global variable }
  1082.   PUSH AX     { store error code }
  1083.   PUSH fnIsFixedDisk  { store function code }
  1084.   CALL ErrorHandler
  1085. @@1:
  1086. End; { IsFixedDisk }
  1087.  
  1088. Function IsNetworkDrive; assembler;
  1089. { ISNETWORKDRIVE - DOS disk service function
  1090.   Description: Ensures whether the specified disk drive is a network drive;
  1091.                fn=4409h
  1092.   Returns: True if drive is a network drive, False if it's a local drive
  1093.   Remarks: Use 0 for detecting the default (current) drive }
  1094. Asm
  1095.   MOV AX,4409h
  1096.   MOV BL,Drive
  1097.   INT DOS
  1098.   JNC @@1
  1099.   MOV DOSResult,AX { save error code in global variable }
  1100.   PUSH AX     { store error code }
  1101.   PUSH fnIsNetworkDrive  { store function code }
  1102.   CALL ErrorHandler
  1103. @@1:
  1104. End; { IsNetworkDrive }
  1105.  
  1106. Function GetDriveType(Drive : byte) : byte; assembler;
  1107. { GETDRIVETYPE - Disk service function
  1108.   Description: Detects the type of the specified drive. Uses IsFixedDisk and
  1109.                IsNetworkDrive functions to produce a result value
  1110.   Returns: One of (dt) constants (see const section)
  1111.   Remarks: Use 0 for detecting the default (current) drive }
  1112. Asm
  1113.   PUSH WORD PTR Drive
  1114.   CALL IsNetworkDrive
  1115.   XOR BL,BL
  1116.   CMP DOSResult,dosrOk
  1117.   JNE @@3
  1118.   CMP AL,True
  1119.   JNE @@1
  1120.   MOV BL,dtRemote
  1121.   JMP @@3
  1122. @@1:
  1123.   PUSH WORD PTR Drive
  1124.   CALL IsFixedDisk
  1125.   XOR BL,BL
  1126.   CMP DOSResult,dosrOk
  1127.   JNE @@3
  1128.   CMP AL,True
  1129.   JNE @@2
  1130.   MOV BL,dtFixed
  1131.   JMP @@3
  1132. @@2:
  1133.   MOV BL,dtRemovable
  1134. @@3:
  1135.   MOV AL,BL
  1136. End; { GetDriveType }
  1137.  
  1138. Function CreateDir; assembler;
  1139. { CREATEDIR - DOS directory function
  1140.   Description: Creates a directory; fn=39h
  1141.   Returns: 0 if successful, negative DOS error code otherwise }
  1142. Asm
  1143. @@1:
  1144.   PUSH DS
  1145.   LDS DX,Dir
  1146.   MOV AH,39h
  1147.   INT DOS
  1148.   POP DS
  1149.   JC  @@2
  1150.   XOR AX,AX
  1151.   MOV DOSResult,dosrOk
  1152.   JMP @@3
  1153. @@2:
  1154.   MOV DOSResult,AX { save error code in global variable }
  1155.   PUSH AX     { store error code }
  1156.   PUSH fnCreateDir  { store function code }
  1157.   CALL ErrorHandler
  1158.   CMP AL,frRetry
  1159.   JE  @@1
  1160.   POP AX
  1161.   NEG AX
  1162. @@3:
  1163. End; { CreateDir }
  1164.  
  1165. Function RemoveDir; assembler;
  1166. { REMOVEDIR - DOS directory function
  1167.   Description: Removes (deletes) a directory; fn=3Ah
  1168.   Returns: 0 if successful, negative DOS error code otherwise }
  1169. Asm
  1170. @@1:
  1171.   PUSH DS
  1172.   LDS DX,Dir
  1173.   MOV AH,3Ah
  1174.   INT DOS
  1175.   POP DS
  1176.   JC  @@2
  1177.   XOR AX,AX
  1178.   MOV DOSResult,dosrOk
  1179.   JMP @@3
  1180. @@2:
  1181.   MOV DOSResult,AX { save error code in global variable }
  1182.   PUSH AX     { store error code }
  1183.   PUSH fnRemoveDir  { store function code }
  1184.   CALL ErrorHandler
  1185.   CMP AL,frRetry
  1186.   JE  @@1
  1187.   POP AX
  1188.   NEG AX
  1189. @@3:
  1190. End; { RemoveDir }
  1191.  
  1192. Function GetCurDir; assembler;
  1193. { GETCURDIR - DOS directory function
  1194.   Description: Retrieves current (active) directory name; fn=47h
  1195.   Returns: 0 if successful, negative DOS error code otherwise }
  1196. Asm
  1197. @@1:
  1198.   PUSH DS
  1199.   LDS SI,Dir
  1200.   MOV DL,Drive
  1201.   MOV AH,47h
  1202.   INT DOS
  1203.   POP DS
  1204.   JC  @@2
  1205.   XOR AX,AX
  1206.   MOV DOSResult,dosrOk
  1207.   JMP @@3
  1208. @@2:
  1209.   MOV DOSResult,AX { save error code in global variable }
  1210.   PUSH AX     { store error code }
  1211.   PUSH fnGetCurDir  { store function number }
  1212.   CALL ErrorHandler
  1213.   CMP AL,frRetry
  1214.   JE  @@1
  1215.   POP AX
  1216.   NEG AX
  1217. @@3:
  1218. End; { GetCurDir }
  1219.  
  1220. Function SetCurDir; assembler;
  1221. { SETCURDIR - DOS directory function
  1222.   Description: Sets current (active) directory; fn=3Bh
  1223.   Returns: 0 if successful, negative DOS error code otherwise }
  1224. Asm
  1225. @@1:
  1226.   PUSH DS
  1227.   LDS DX,Dir
  1228.   MOV AH,3Bh
  1229.   INT DOS
  1230.   POP DS
  1231.   JC  @@2
  1232.   XOR AX,AX
  1233.   MOV DOSResult,AX
  1234.   JMP @@3
  1235. @@2:
  1236.   MOV DOSResult,AX { save error code in global variable }
  1237.   PUSH AX     { store error code }
  1238.   PUSH fnSetCurDir  { store function code }
  1239.   CALL ErrorHandler
  1240.   CMP AL,frRetry
  1241.   JE  @@1
  1242.   POP AX
  1243.   NEG AX
  1244. @@3:
  1245. End; { SetCurDir }
  1246.  
  1247. Function DeleteFile; assembler;
  1248. { DELETEFILE - DOS file function
  1249.   Description: Deletes a file; fn=41h
  1250.   Returns: 0 if successful, negative DOS error code otherwise }
  1251. Asm
  1252. @@1:
  1253.   PUSH DS
  1254.   LDS DX,Path
  1255.   MOV AH,41h
  1256.   INT DOS
  1257.   POP DS
  1258.   JC  @@2
  1259.   XOR AX,AX
  1260.   MOV DOSResult,dosrOk
  1261.   JMP @@3
  1262. @@2:
  1263.   MOV DOSResult,AX { save error code in global variable }
  1264.   PUSH AX     { store error code }
  1265.   PUSH fnDeleteFile  { store function code }
  1266.   CALL ErrorHandler
  1267.   CMP AL,frRetry
  1268.   JE  @@1
  1269.   POP AX
  1270.   NEG AX
  1271. @@3:
  1272. End; { DeleteFile }
  1273.  
  1274. Function RenameFile; assembler;
  1275. { RENAMEFILE - DOS file function
  1276.   Description: Renames/moves a file; fn=56h
  1277.   Returns: 0 if successful, negative error code otherwise }
  1278. Asm
  1279. @@1:
  1280.   PUSH DS
  1281.   LDS DX,OldPath
  1282.   LES DI,NewPath
  1283.   MOV AH,56h
  1284.   INT DOS
  1285.   POP DS
  1286.   JC  @@2
  1287.   XOR AX,AX
  1288.   MOV DOSResult,dosrOk
  1289.   JMP @@3
  1290. @@2:
  1291.   MOV DOSResult,AX { save error code in global variable }
  1292.   PUSH AX     { store error code }
  1293.   PUSH fnRenameFile  { store function code }
  1294.   CALL ErrorHandler
  1295.   CMP AL,frRetry
  1296.   JE  @@1
  1297.   POP AX
  1298.   NEG AX
  1299. @@3:
  1300. End; { RenameFile }
  1301.  
  1302. Function ExistsFile; assembler;
  1303. { EXISTSFILE - DOS file function
  1304.   Description: Determines whether the file exists; fn=4Eh
  1305.   Returns: TRUE if the file exists, FALSE - otherwise }
  1306. Asm
  1307.   PUSH DS
  1308.   LDS DX,Path
  1309.   MOV AH,4Eh
  1310.   INT DOS
  1311.   POP DS
  1312.   JNC @@1
  1313.   XOR AL,AL
  1314.   JMP @@2
  1315. @@1:
  1316.   MOV AL,True
  1317. @@2:
  1318. End; { ExistsFile }
  1319.  
  1320. Function GetFileAttr; assembler;
  1321. { GETFILEATTR - DOS file function
  1322.   Description: Gets file attributes; fn=43h,AL=0
  1323.   Returns: File attributes if no error, negative DOS error code otherwise }
  1324. Asm
  1325. @@1:
  1326.   PUSH DS
  1327.   LDS DX,Path
  1328.   MOV AX,4300h
  1329.   INT DOS
  1330.   POP DS
  1331.   JC  @@2
  1332.   MOV AX,CX
  1333.   MOV DOSResult,dosrOk
  1334.   JMP @@3
  1335. @@2:
  1336.   MOV DOSResult,AX { save error code in global variable }
  1337.   PUSH AX     { store error code }
  1338.   PUSH fnGetFileAttr  { store function code }
  1339.   CALL ErrorHandler
  1340.   CMP AL,frRetry
  1341.   JE  @@1
  1342.   POP AX
  1343.   NEG AX
  1344. @@3:
  1345. End; { GetFileAttr }
  1346.  
  1347. Function SetFileAttr; assembler;
  1348. { SETFILEATTR - DOS file function
  1349.   Description: Sets file attributes; fn=43h,AL=1
  1350.   Returns: 0 if no error, negative DOS error code otherwise }
  1351. Asm
  1352. @@1:
  1353.   PUSH DS
  1354.   LDS DX,Path
  1355.   MOV CX,Attr
  1356.   MOV AX,4301h
  1357.   INT DOS
  1358.   POP DS
  1359.   JC  @@2
  1360.   XOR AX,AX
  1361.   MOV DOSResult,dosrOk
  1362.   JMP @@3
  1363. @@2:
  1364.   MOV DOSResult,AX { save error code in global variable }
  1365.   PUSH AX     { store error code }
  1366.   PUSH fnSetFileAttr  { store function code }
  1367.   CALL ErrorHandler
  1368.   CMP AL,frRetry
  1369.   JE  @@1
  1370.   POP AX
  1371.   NEG AX
  1372. @@3:
  1373. End; { GetFileAttr }
  1374.  
  1375. Function FindFirst; assembler;
  1376. { FINDFIRST - DOS file service function
  1377.   Description: Searches the specified (or current) directory for
  1378.                the first entry that matches the specified filename and
  1379.                attributes; fn=4E00h
  1380.   Returns: 0 if successful, negative DOS error code otherwise }
  1381. Asm
  1382. @@1:
  1383.   PUSH DS
  1384.   LDS DX,F
  1385.   MOV AH,1AH
  1386.   INT DOS
  1387.   POP DS
  1388.   LES DI,Path
  1389.   MOV CX,Attr
  1390.   MOV AH,4EH
  1391.   CALL AnsiDosFunc
  1392.   MOV DOSResult,dosrOk
  1393.   JC  @@2
  1394. {$IFDEF Windows}
  1395.   LES DI,F
  1396.   ADD DI,OFFSET TSearchRec.Name
  1397.   PUSH ES
  1398.   PUSH DI
  1399.   PUSH ES
  1400.   PUSH DI
  1401.   CALL OemToAnsi
  1402. {$ENDIF}
  1403.   XOR AX,AX
  1404.   JMP @@3
  1405. @@2:
  1406.   MOV DOSResult,AX { save error code in global variable }
  1407.   PUSH AX     { store error code }
  1408.   PUSH fnFindFirst  { store function code }
  1409.   CALL ErrorHandler
  1410.   CMP AL,frRetry
  1411.   JE  @@1
  1412.   POP AX
  1413. @@3:
  1414.   NEG AX
  1415. End; { FindFirst }
  1416.  
  1417. Function FindNext; assembler;
  1418. { FINDNEXT - DOS file service function
  1419.   Description: Returs the next entry that matches the name and
  1420.                attributes specified in a previous call to FindFirst.
  1421.                The search record must be one passed to FindFirst
  1422.   Returns: 0 if successful, negative DOS error code otherwise }
  1423. Asm
  1424. @@1:
  1425.   PUSH DS
  1426.   LDS DX,F
  1427.   MOV AH,1AH
  1428.   INT DOS
  1429.   POP DS
  1430.   MOV AH,4FH
  1431.   MOV DOSResult,dosrOk
  1432.   INT DOS
  1433.   JC  @@2
  1434. {$IFDEF Windows}
  1435.   LES DI,F
  1436.   ADD DI,OFFSET TSearchRec.Name
  1437.   PUSH ES
  1438.   PUSH DI
  1439.   PUSH ES
  1440.   PUSH DI
  1441.   CALL OemToAnsi
  1442. {$ENDIF}
  1443.   XOR AX,AX
  1444.   JMP @@3
  1445. @@2:
  1446.   MOV DOSResult,AX { save error code in global variable }
  1447.   PUSH AX     { store error code }
  1448.   PUSH fnFindNext  { store function code }
  1449.   CALL ErrorHandler
  1450.   CMP AL,frRetry
  1451.   JE  @@1
  1452.   POP AX
  1453. @@3:
  1454.   NEG AX
  1455. End; { FindNext }
  1456.  
  1457. Procedure UnpackTime; assembler;
  1458. { UNPACKTIME - Service function
  1459.   Description: Converts a 4-byte packed date/time returned by
  1460.                FindFirst, FindNext or GetFTime into a TDateTime record }
  1461. Asm
  1462.   LES DI,T
  1463.   CLD
  1464.   MOV AX,WORD PTR [P+2]
  1465.   MOV CL,9
  1466.   SHR AX,CL
  1467.   ADD AX,1980
  1468.   STOSW
  1469.   MOV AX,WORD PTR [P+2]
  1470.   MOV CL,5
  1471.   SHR AX,CL
  1472.   AND AX,15
  1473.   STOSW
  1474.   MOV AX,WORD PTR [P+2]
  1475.   AND AX,31
  1476.   STOSW
  1477.   MOV AX,P.Word[0]
  1478.   MOV CL,11
  1479.   SHR AX,CL
  1480.   STOSW
  1481.   MOV AX,WORD PTR [P+2]
  1482.   MOV CL,5
  1483.   SHR AX,CL
  1484.   AND AX,63
  1485.   STOSW
  1486.   MOV AX,WORD PTR [P]
  1487.   AND AX,31
  1488.   SHL AX,1
  1489.   STOSW
  1490. End; { UnpackTime }
  1491.  
  1492. Function PackTime; assembler;
  1493. { PACKTIME - Service function
  1494.   Decription: Converts a TDateTime record into a 4-byte packed
  1495.               date/time used by SetFTime
  1496.   Returns: 4-byte long integer corresponding to packed date/time }
  1497. Asm
  1498.   PUSH DS
  1499.   LDS SI,T
  1500.   CLD
  1501.   LODSW
  1502.   SUB AX,1980
  1503.   MOV CL,9
  1504.   SHL AX,CL
  1505.   XCHG AX,DX
  1506.   LODSW
  1507.   MOV CL,5
  1508.   SHL AX,CL
  1509.   ADD DX,AX
  1510.   LODSW
  1511.   ADD DX,AX
  1512.   LODSW
  1513.   MOV CL,11
  1514.   SHL AX,CL
  1515.   XCHG AX,BX
  1516.   LODSW
  1517.   MOV CL,5
  1518.   SHL AX,CL
  1519.   ADD BX,AX
  1520.   LODSW
  1521.   SHR AX,1
  1522.   ADD AX,BX
  1523.   POP DS
  1524. End; { PackTime }
  1525.  
  1526. Function h_CreateFile; assembler;
  1527. { H_CREATEFILE - DOS Handle file function
  1528.   Description: Creates a file; fn=3Ch
  1529.   Returns: File handle if successful, 0 if unsuccessful }
  1530. Asm
  1531. @@1:
  1532.   PUSH DS
  1533.   LDS DX,Path
  1534.   MOV CX,0
  1535.   MOV AH,5Bh
  1536.   INT DOS
  1537.   POP DS
  1538.   JC  @@2
  1539.   MOV DOSResult,dosrOk
  1540.   JMP @@3
  1541. @@2:
  1542.   MOV DOSResult,AX { save error code in global variable }
  1543.   PUSH AX     { store error code }
  1544.   PUSH fnCreateFile  { store function code }
  1545.   CALL ErrorHandler
  1546.   CMP AL,frRetry
  1547.   JE  @@1
  1548.   XOR AX,AX
  1549. @@3:
  1550. End; { h_CreateFile }
  1551.  
  1552. Function h_CreateTempFile; assembler;
  1553. { H_CREATETEMPFILE - DOS Handle file function
  1554.   Description: Creates a temporary file; fn=5Ah
  1555.   Returns: File handle if successful, 0 if unsuccessful }
  1556. Asm
  1557. @@1:
  1558.   PUSH DS
  1559.   LDS DX,Path
  1560.   MOV CX,0 { file attribute here, 0 used for normal }
  1561.   MOV AH,5Ah
  1562.   INT DOS
  1563.   POP DS
  1564.   JC  @@2
  1565.   MOV DOSResult,dosrOk
  1566.   JMP @@3
  1567. @@2:
  1568.   MOV DOSResult,AX { save error code in global variable }
  1569.   PUSH AX     { store error code }
  1570.   PUSH fnCreateTempFile  { store function code }
  1571.   CALL ErrorHandler
  1572.   CMP AL,frRetry
  1573.   JE  @@1
  1574.   XOR AX,AX
  1575. @@3:
  1576. End; { h_CreateTempFile }
  1577.  
  1578. Function h_OpenFile; assembler;
  1579. { H_OPENFILE - DOS Handle file function
  1580.   Description: Opens a file for input, output or input/output; fn=3Dh
  1581.   Returns: File handle if successful, 0 if unsuccessful }
  1582. Asm
  1583. @@1:
  1584.   PUSH DS
  1585.   LDS DX,Path
  1586.   MOV AH,3Dh
  1587.   MOV AL,Mode
  1588.   INT DOS
  1589.   POP DS
  1590.   JC  @@2
  1591.   MOV DOSResult,dosrOk
  1592.   JMP @@3
  1593. @@2:
  1594.   MOV DOSResult,AX { save error code in global variable }
  1595.   PUSH AX     { store error code }
  1596.   PUSH fnOpenFile  { store function code }
  1597.   CALL ErrorHandler
  1598.   CMP AL,frRetry
  1599.   JE  @@1
  1600.   XOR AX,AX
  1601. @@3:
  1602. End; { h_OpenFile }
  1603.  
  1604. Function h_Read; assembler;
  1605. { H_READ - DOS Handle file function
  1606.   Description: Reads a memory block from file; fn=3Fh
  1607.   Returns: Actual number of bytes read }
  1608. Asm
  1609. @@1:
  1610.   PUSH DS
  1611.   LDS DX,Buffer
  1612.   MOV CX,Count
  1613.   MOV BX,Handle
  1614.   MOV AH,3Fh
  1615.   INT DOS
  1616.   POP DS
  1617.   MOV DOSResult,dosrOk
  1618.   JNC @@2
  1619.   MOV DOSResult,AX { save error code in global variable }
  1620.   PUSH AX     { store error code }
  1621.   PUSH fnRead  { store function code }
  1622.   CALL ErrorHandler
  1623.   CMP AL,frRetry
  1624.   JE  @@1
  1625. @@2:
  1626. End; { h_Read }
  1627.  
  1628. Function h_Write; assembler;
  1629. { H_WRITE - DOS Handle file function
  1630.   Description: Writes a memory block to file; fn=40h
  1631.   Returns: Actual number of bytes written }
  1632. Asm
  1633. @@1:
  1634.   PUSH DS
  1635.   LDS DX,Buffer
  1636.   MOV CX,Count
  1637.   MOV BX,Handle
  1638.   MOV AH,40h
  1639.   INT DOS
  1640.   POP DS
  1641.   MOV DOSResult,dosrOk
  1642.   JNC @@2
  1643.   MOV DOSResult,AX { save error code in global variable }
  1644.   PUSH AX     { store error code }
  1645.   PUSH fnWrite  { store function code }
  1646.   CALL ErrorHandler
  1647.   CMP AL,frRetry
  1648.   JE  @@1
  1649. @@2:
  1650. End; { h_Write }
  1651.  
  1652. Function h_Seek; assembler;
  1653. { H_SEEK - DOS Handle file function
  1654.   Description: Seeks to a specified file position; fn=42h
  1655.                Start is one of the (sk) constants and points to a relative
  1656.                seek offset position
  1657.   Returns: Current file position if successful, 0 - otherwise }
  1658. Asm
  1659. @@1:
  1660.   MOV CX,WORD PTR [SeekPos+2]
  1661.   MOV DX,WORD PTR [SeekPos]
  1662.   MOV BX,Handle
  1663.   MOV AL,Start
  1664.   MOV AH,42h
  1665.   MOV DOSResult,dosrOk
  1666.   INT DOS
  1667.   JNC @@2
  1668.   MOV DOSResult,AX { save error code in global variable }
  1669.   PUSH AX     { store error code }
  1670.   PUSH fnSeek  { store function number }
  1671.   CALL ErrorHandler
  1672.   CMP AL,frRetry
  1673.   JE  @@1
  1674. @@2:
  1675. End; { h_Seek }
  1676.  
  1677. Function h_FilePos;
  1678. { H_GETPOS - DOS Handle file function
  1679.   Description: Calls h_Seek to determine file active position
  1680.   Returns: Current file (seek) position number in long integer }
  1681. Begin
  1682.   h_FilePos := h_Seek(Handle, 0, skPos)
  1683. End; { h_FilePos }
  1684.  
  1685. Function h_FileSize;
  1686. { H_FILESIZE - DOS Handle file function
  1687.   Description: Determines file size
  1688.   Returns: File size in bytes }
  1689. var SavePos, Size : longint;
  1690. Begin
  1691.   SavePos := h_FilePos(Handle);
  1692.   h_FileSize := h_Seek(Handle, 0, skEnd);
  1693.   h_Seek(Handle, SavePos, skStart)
  1694. End; { h_FileSize }
  1695.  
  1696. Function h_Eof; assembler;
  1697. { H_EOF - DOS Handle file function
  1698.   Description: Checks if the current file position is equal to file size
  1699.                and then returns True
  1700.   Returns: True if end of file detected, False - otherwise }
  1701. var Size : longint;
  1702. Asm
  1703.   PUSH Handle
  1704.   CALL h_FileSize               { Get file size in AX:DX }
  1705.   MOV WORD PTR [Size],AX        { Store high word }
  1706.   MOV WORD PTR [Size+2],DX      { Store low word }
  1707.   PUSH Handle
  1708.   CALL h_FilePos                 { Get current file position }
  1709.   XOR CL,CL
  1710.   CMP AX,WORD PTR [Size]
  1711.   JNE @@1
  1712.   CMP DX,WORD PTR [Size+2]
  1713.   JNE @@1
  1714.   MOV CL,True
  1715. @@1:
  1716.   MOV AL,CL
  1717. End; { h_GetPos }
  1718.  
  1719. Function h_GetFTime; assembler;
  1720. { H_GETFTIME - DOS Handle file function
  1721.   Description: Returns file update date and time values; fn=5700h
  1722.   Returns: Date and time values in long integer
  1723.            or negative DOS error code if an error occured }
  1724. Asm
  1725. @@1:
  1726.   MOV BX,Handle
  1727.   MOV AX,5700h { read date and time }
  1728.   MOV DOSResult,dosrOk
  1729.   INT DOS
  1730.   JNC @@2
  1731.   MOV DOSResult,AX { save error code in global variable }
  1732.   PUSH AX     { store error code }
  1733.   PUSH fnGetFDateTime  { store function number }
  1734.   CALL ErrorHandler
  1735.   CMP AL,frRetry
  1736.   JE  @@1
  1737.   POP AX
  1738.   NEG AX
  1739. @@2:
  1740. End; { h_GetFTime }
  1741.  
  1742. Function h_SetFTime; assembler;
  1743. { H_SETFTIME - DOS Handle file function
  1744.   Description: Sets file date and time; fn=5701h
  1745.   Returns: New date and time values in long integer
  1746.            or negative DOS error code if an error occured }
  1747. Asm
  1748. @@1:
  1749.   MOV CX,WORD PTR [DateTime]
  1750.   MOV DX,WORD PTR [DateTime+2]
  1751.   MOV BX,Handle
  1752.   MOV AX,5701h { read date and time }
  1753.   MOV DOSResult,dosrOk
  1754.   INT DOS
  1755.   JNC @@2
  1756.   MOV DOSResult,AX { save error code in global variable }
  1757.   PUSH AX     { store error code }
  1758.   PUSH fnSetFDateTime  { store function number }
  1759.   CALL ErrorHandler
  1760.   CMP AL,frRetry
  1761.   JE  @@1
  1762.   POP AX
  1763.   NEG AX
  1764. @@2:
  1765. End; { h_SetFTime }
  1766.  
  1767. Function h_CloseFile; assembler;
  1768. { H_CLOSEFILE - DOS Handle file function
  1769.   Description: Closes open file; fn=3Eh
  1770.   Returns: 0 if successful, negative DOS error code otherwise }
  1771. Asm
  1772. @@1:
  1773.   MOV BX,Handle
  1774.   MOV AH,3Eh
  1775.   INT DOS
  1776.   JC  @@2
  1777.   XOR AX,AX
  1778.   MOV DOSResult,dosrOk
  1779.   JMP @@3
  1780. @@2:
  1781.   MOV DOSResult,AX { save error code in global variable }
  1782.   PUSH AX     { store error code }
  1783.   PUSH fnCloseFile  { store function number }
  1784.   CALL ErrorHandler
  1785.   CMP AL,frRetry
  1786.   JE  @@1
  1787.   POP AX
  1788.   NEG AX
  1789. @@3:
  1790. End; { h_CloseFile }
  1791.  
  1792. Function MemAlloc; assembler;
  1793. Asm
  1794. @@1:
  1795.   MOV DOSResult,dosrOk
  1796.   MOV AX,WORD PTR [Size]
  1797.   MOV DX,WORD PTR [Size+2]
  1798.   MOV CX,16
  1799.   DIV CX
  1800.   INC AX
  1801.   MOV BX,AX
  1802.   MOV AH,48h
  1803.   INT DOS
  1804.   JNC @@2
  1805.   MOV DOSResult,AX { save error code in global variable }
  1806.   PUSH AX     { store error code }
  1807.   PUSH fnMemAlloc  { store function number }
  1808.   CALL ErrorHandler
  1809.   CMP AL,frRetry
  1810.   JE  @@1
  1811.   XOR AX,AX
  1812. @@2:
  1813.   MOV DX,AX
  1814.   XOR AX,AX
  1815. End; { MemAlloc }
  1816.  
  1817. Function MemFree; assembler;
  1818. Asm
  1819.   MOV DOSResult,dosrOk
  1820.   MOV ES,WORD PTR [P+2]
  1821.   MOV AH,49h
  1822.   INT DOS
  1823.   JNC @@1
  1824.   MOV DOSResult,AX
  1825.   PUSH AX
  1826.   PUSH fnMemFree
  1827.   CALL ErrorHandler
  1828. @@1:
  1829.   MOV AX,DOSResult
  1830.   NEG AX
  1831. End; { MemFree }
  1832.  
  1833. Function FileSearch; assembler;
  1834. { FileSearch searches for the file given by Name in the list of }
  1835. { directories given by List. The directory paths in List must   }
  1836. { be separated by semicolons. The search always starts with the }
  1837. { current directory of the current drive. If the file is found, }
  1838. { FileSearch stores a concatenation of the directory path and   }
  1839. { the file name in Dest. Otherwise FileSearch stores an empty   }
  1840. { string in Dest. The maximum length of the result is defined   }
  1841. { by the fsPathName constant. The returned value is Dest.       }
  1842. Asm
  1843.   PUSH DS
  1844.   CLD
  1845.   LDS SI,List
  1846.   LES DI,Dest
  1847.   MOV CX,fsPathName
  1848. @@1:
  1849.   PUSH DS
  1850.   PUSH SI
  1851.   JCXZ @@3
  1852.   LDS SI,Name
  1853. @@2:
  1854.   LODSB
  1855.   OR  AL,AL
  1856.   JE  @@3
  1857.   STOSB
  1858.   LOOP @@2
  1859. @@3:
  1860.   XOR AL,AL
  1861.   STOSB
  1862.   LES DI,Dest
  1863.   MOV AX,4300H
  1864.   CALL AnsiDosFunc
  1865.   POP SI
  1866.   POP DS
  1867.   JC  @@4
  1868.   TEST CX,18H
  1869.   JE  @@9
  1870. @@4:
  1871.   LES DI,Dest
  1872.   MOV CX,fsPathName
  1873.   XOR AH,AH
  1874.   LODSB
  1875.   OR  AL,AL
  1876.   JE  @@8
  1877. @@5:
  1878.   CMP AL,';'
  1879.   JE  @@7
  1880.   JCXZ @@6
  1881.   MOV AH,AL
  1882.   STOSB
  1883.   DEC CX
  1884. @@6:
  1885.   LODSB
  1886.   OR  AL,AL
  1887.   JNE @@5
  1888.   DEC SI
  1889. @@7:
  1890.   JCXZ @@1
  1891.   CMP AH,':'
  1892.   JE  @@1
  1893.   MOV AL,'\'
  1894.   CMP AL,AH
  1895.   JE  @@1
  1896.   STOSB
  1897.   DEC CX
  1898.   JMP @@1
  1899. @@8:
  1900.   STOSB
  1901. @@9:
  1902.   MOV AX,WORD PTR [Dest]
  1903.   MOV DX,WORD PTR [Dest+2]
  1904.   POP DS
  1905. End; { FileSearch }
  1906.  
  1907. Function FileExpand; assembler;
  1908. { FileExpand fully expands the file name in Name, and stores    }
  1909. { the result in Dest. The maximum length of the result is       }
  1910. { defined by the fsPathName constant. The result is an all }
  1911. { upper case string consisting of a drive letter, a colon, a }
  1912. { root relative directory path, and a file name. Embedded '.' }
  1913. { and '..' directory references are removed, and all name and }
  1914. { extension components are truncated to 8 and 3 characters. The }
  1915. { returned value is Dest.                }
  1916.  
  1917. Asm
  1918.   PUSH DS
  1919.   CLD
  1920.   LDS SI,Name
  1921.   LEA DI,TempStr
  1922.   PUSH SS
  1923.   POP ES
  1924.   LODSW
  1925.   OR  AL,AL
  1926.   JE  @@1
  1927.   CMP AH,':'
  1928.   JNE @@1
  1929.   CMP AL,'a'
  1930.   JB  @@2
  1931.   CMP AL,'z'
  1932.   JA  @@2
  1933.   SUB AL,20H
  1934.   JMP @@2
  1935. @@1:
  1936.   DEC SI
  1937.   DEC SI
  1938.   MOV AH,19H
  1939.   INT DOS
  1940.   ADD AL,'A'
  1941.   MOV AH,':'
  1942. @@2:
  1943.   STOSW
  1944.   CMP [SI].Byte,'\'
  1945.   JE  @@3
  1946.   SUB AL,'A'-1
  1947.   MOV DL,AL
  1948.   MOV AL,'\'
  1949.   STOSB
  1950.   PUSH DS
  1951.   PUSH SI
  1952.   MOV AH,47H
  1953.   MOV SI,DI
  1954.   PUSH ES
  1955.   POP DS
  1956.   INT DOS
  1957.   POP SI
  1958.   POP DS
  1959.   JC  @@3
  1960.   XOR AL,AL
  1961.   CMP AL,ES:[DI]
  1962.   JE  @@3
  1963. {$IFDEF Windows}
  1964.   PUSH ES
  1965.   PUSH ES
  1966.   PUSH DI
  1967.   PUSH ES
  1968.   PUSH DI
  1969.   CALL OemToAnsi
  1970.   POP ES
  1971. {$ENDIF}
  1972.   MOV CX,0FFFFH
  1973.   XOR AL,AL
  1974.   CLD
  1975.   REPNE SCASB
  1976.   DEC DI
  1977.   MOV AL,'\'
  1978.   STOSB
  1979. @@3:
  1980.   MOV CX,8
  1981. @@4:
  1982.   LODSB
  1983.   OR  AL,AL
  1984.   JE  @@7
  1985.   CMP AL,'\'
  1986.   JE  @@7
  1987.   CMP AL,'.'
  1988.   JE  @@6
  1989.   JCXZ @@4
  1990.   DEC CX
  1991. {$IFNDEF Windows}
  1992.   CMP AL,'a'
  1993.   JB  @@5
  1994.   CMP AL,'z'
  1995.   JA  @@5
  1996.   SUB AL,20H
  1997. {$ENDIF}
  1998. @@5:
  1999.   STOSB
  2000.   JMP @@4
  2001. @@6:
  2002.   MOV CL,3
  2003.   JMP @@5
  2004. @@7:
  2005.   CMP ES:[DI-2].Word,'.\'
  2006.   JNE @@8
  2007.   DEC DI
  2008.   DEC DI
  2009.   JMP @@10
  2010. @@8:
  2011.   CMP ES:[DI-2].Word,'..'
  2012.   JNE @@10
  2013.   CMP ES:[DI-3].Byte,'\'
  2014.   JNE @@10
  2015.   SUB DI,3
  2016.   CMP ES:[DI-1].Byte,':'
  2017.   JE  @@10
  2018. @@9:
  2019.   DEC DI
  2020.   CMP ES:[DI].Byte,'\'
  2021.   JNE @@9
  2022. @@10:
  2023.   MOV CL,8
  2024.   OR  AL,AL
  2025.   JNE @@5
  2026.   CMP ES:[DI-1].Byte,':'
  2027.   JNE @@11
  2028.   MOV AL,'\'
  2029.   STOSB
  2030. @@11:
  2031.   LEA SI,TempStr
  2032.   PUSH SS
  2033.   POP DS
  2034.   MOV CX,DI
  2035.   SUB CX,SI
  2036.   CMP CX,79
  2037.   JBE @@12
  2038.   MOV CX,79
  2039. @@12:
  2040.   LES DI,Dest
  2041.   PUSH ES
  2042.   PUSH DI
  2043. {$IFDEF Windows}
  2044.   PUSH ES
  2045.   PUSH DI
  2046. {$ENDIF}
  2047.   REP MOVSB
  2048.   XOR AL,AL
  2049.   STOSB
  2050. {$IFDEF Windows}
  2051.   CALL AnsiUpper
  2052. {$ENDIF}
  2053.   POP AX
  2054.   POP DX
  2055.   POP DS
  2056. End; { FileExpand }
  2057.  
  2058. {$W+}
  2059. Function FileSplit;
  2060. { FileSplit splits the file name specified by Path into its     }
  2061. { three components. Dir is set to the drive and directory path  }
  2062. { with any leading and trailing backslashes, Name is set to the }
  2063. { file name, and Ext is set to the extension with a preceding   }
  2064. { period. If a component string parameter is NIL, the           }
  2065. { corresponding part of the path is not stored. If the path     }
  2066. { does not contain a given component, the returned component    }
  2067. { string is empty. The maximum lengths of the strings returned  }
  2068. { in Dir, Name, and Ext are defined by the fsDirectory,         }
  2069. { fsFileName, and fsExtension constants. The returned value is  }
  2070. { a combination of the fcDirectory, fcFileName, and fcExtension }
  2071. { bit masks, indicating which components were present in the    }
  2072. { path. If the name or extension contains any wildcard          }
  2073. { characters (* or ?), the fcWildcards flag is set in the       }
  2074. { returned value.                                               }
  2075. var
  2076.   DirLen, NameLen, Flags : word;
  2077.   NamePtr, ExtPtr : PChar;
  2078. begin
  2079.   NamePtr := StrRScan(Path, '\');
  2080.   if NamePtr = nil then NamePtr := StrRScan(Path, ':');
  2081.   if NamePtr = nil then NamePtr := Path else Inc(NamePtr);
  2082.   ExtPtr := StrScan(NamePtr, '.');
  2083.   if ExtPtr = nil then ExtPtr := StrEnd(NamePtr);
  2084.   DirLen := NamePtr - Path;
  2085.   if DirLen > fsDirectory then DirLen := fsDirectory;
  2086.   NameLen := ExtPtr - NamePtr;
  2087.   if NameLen > fsFilename then NameLen := fsFilename;
  2088.   Flags := 0;
  2089.   if (StrScan(NamePtr, '?') <> nil) or (StrScan(NamePtr, '*') <> nil) then
  2090.     Flags := fcWildcards;
  2091.   if DirLen <> 0 then Flags := Flags or fcDirectory;
  2092.   if NameLen <> 0 then Flags := Flags or fcFilename;
  2093.   if ExtPtr[0] <> #0 then Flags := Flags or fcExtension;
  2094.   if Dir <> nil then StrLCopy(Dir, Path, DirLen);
  2095.   if Name <> nil then StrLCopy(Name, NamePtr, NameLen);
  2096.   if Ext <> nil then StrLCopy(Ext, ExtPtr, fsExtension);
  2097.   FileSplit := Flags;
  2098. End; { FileSplit }
  2099. {$W-}
  2100.  
  2101. Function StdErrorProc(ErrCode : integer; FuncCode : word) : byte; far;
  2102. assembler;
  2103. { Default error handler procedure called from EnhDOS functions }
  2104. Asm
  2105.   MOV AL,frOk   { Return zero }
  2106. End; { StdErrorProc }
  2107.  
  2108.  
  2109. const WrongDOSVersion : PChar = 'DOS 3.1 or greater required.'#13#10'$';
  2110.  
  2111. Begin
  2112.   asm
  2113.     MOV AH,30h { Get DOS version }
  2114.     INT DOS
  2115.     CMP AL,3
  2116.     JGE @@continue { if greater than or equal to 3 then continue else exit }
  2117.     PUSH DS
  2118.     LDS DX,WrongDOSVersion
  2119.     MOV AH,09h
  2120.     INT DOS
  2121.     MOV AH,4Ch
  2122.     INT DOS
  2123.   @@continue:
  2124.     LES DI,Copyright
  2125.   end;
  2126.   DOSResult := dosrOk;
  2127.   SetErrorHandler(StdErrorProc)
  2128. End. { EnhDOS+ }
  2129.  
  2130. { -------------------------------------   DEMO ------------------   }
  2131. { ***** ENHDDEMO.PAS ***** }
  2132.  
  2133. Program DemoEnhDOS;
  2134. { Copyright (c) 1994 by Andrew Eigus   Fido Net 2:5100/33 }
  2135. { EnhDOS+ (Int21) demo program }
  2136.  
  2137. {$M 8192,0,0}
  2138. { no heap size, couz using own memeory allocation }
  2139.  
  2140. (* Simple copy file program *)
  2141.  
  2142. uses EnhDOS, Strings;
  2143.  
  2144. const BufSize = 65535; { may be larger; you may allocate more }
  2145.  
  2146. var
  2147.   Buffer : pointer;
  2148.   InputFile, OutputFile : array[0..63] of Char;
  2149.   Handle1, Handle2 : THandle;
  2150.   BytesRead : word;
  2151.  
  2152. Function Int21ErrorHandler(ErrCode : integer; FuncCode : word) : byte; far;
  2153. var fn : array[0..20] of Char;
  2154. Begin
  2155.   case FuncCode of
  2156.     fnOpenFile: StrCopy(fn, 'h_OpenFile');
  2157.     fnCreateFile: StrCopy(fn, 'h_CreateFile');
  2158.     fnRead: StrCopy(fn, 'h_Read');
  2159.     fnWrite: StrCopy(fn, 'h_Write');
  2160.     fnSeek: StrCopy(fn, 'h_Seek');
  2161.     fnCloseFile: StrCopy(fn, 'h_CloseFile');
  2162.     fnMemAlloc: StrCopy(fn, 'MemAlloc');
  2163.     fnDeleteFile: Exit;
  2164.     else fn[0] := #0
  2165.   end;
  2166.   WriteLn('DOS Error ', ErrCode, ' in function ', FuncCode, ' (', fn, ')');
  2167.   { actually for function return code see fr consts in the EnhDOS const
  2168.     section }
  2169. End; { Int21ErrorHandler }
  2170.  
  2171. Begin
  2172.   SetErrorHandler(Int21ErrorHandler);
  2173.  
  2174.   WriteLn('EnhDOS+ demo program: copies one file to another');
  2175.   repeat
  2176.     if ParamCount > 0 then
  2177.       StrPCopy(InputFile, ParamStr(1))
  2178.     else
  2179.     begin
  2180.       Write('Enter file name to read from: ');
  2181.       ReadLn(InputFile)
  2182.     end;
  2183.     if ParamCount > 1 then
  2184.       StrPCopy(OutputFile, ParamStr(2))
  2185.     else
  2186.     begin
  2187.       Write('Enter file name to write to:  ');
  2188.       ReadLn(OutputFile)
  2189.     end;
  2190.     WriteLn
  2191.   until (StrLen(InputFile) > 0) and (StrLen(OutputFile) > 0);
  2192.  
  2193.   if not ExistsFile(InputFile) then
  2194.   begin
  2195.     WriteLn('File not found: ', InputFile);
  2196.     Halt(1)
  2197.   end;
  2198.  
  2199.   Buffer := MemAlloc(BufSize);
  2200.  
  2201.   Write('Copying... ');
  2202.  
  2203.   Handle1 := h_OpenFile(InputFile, omRead);
  2204.   if Handle1 <> 0 then
  2205.   begin
  2206.     DeleteFile(OutputFile);
  2207.     Handle2 := h_CreateFile(OutputFile);
  2208.     if Handle2 <> 0 then
  2209.     begin
  2210.       BytesRead := 1;
  2211.  
  2212.       while (BytesRead > 0) and (DOSResult = dosrOk) do
  2213.       begin
  2214.         BytesRead := h_Read(Handle1, Buffer^, BufSize);
  2215.  
  2216.         if DOSResult <> dosrOk then
  2217.           { read error then }
  2218.           WriteLn('Error reading from input file');
  2219.  
  2220.         if h_Write(Handle2, Buffer^, BytesRead) <> BytesRead then
  2221.           { write error then }
  2222.         begin
  2223.           WriteLn('Error writing to output file');
  2224.           DOSResult := $FF
  2225.         end
  2226.       end;
  2227.       if DOSResult = dosrOk then WriteLn('File copied OK');
  2228.       h_CloseFile(Handle2)
  2229.     end;
  2230.     h_CloseFile(Handle1)
  2231.   end;
  2232.  
  2233.   MemFree(Buffer)
  2234. End. { DemoEnhDOS }
  2235.  
  2236.